#include "SKThread.hpp"


bool SKThread::initialize()
{
    if (pthread_mutex_init(&accessLock_, NULL))
    {
	cerr << "Error initializing the SKThread access mutexes" << endl;
	return false;
    }

    if (pthread_mutex_init(&readLock_, NULL))
    {
	cerr << "Error initializing the SKThread read mutexes" << endl;
	return false;
    }

    if (pthread_cond_init(&accessCond_, NULL))
    {
	cerr << "Error initializing the SKThread conditional variables" << endl;
	return false;
    }

    return true;
}

void SKThread::readerLock()
{
    pthread_mutex_lock(&accessLock_);
    while(writer_ || writerWaiting_) // no readers allowed while a writer is in
	pthread_cond_wait(&accessCond_, &accessLock_);
    pthread_mutex_lock(&readLock_);
    readerCount_++; // multiple threads will try updating the count
    pthread_mutex_unlock(&readLock_);
    pthread_mutex_unlock(&accessLock_);
}

void SKThread::readerUnlock()
{
    pthread_mutex_lock(&accessLock_);
    readerCount_--;
    // broadcast a signal on the conditional variable
    pthread_cond_broadcast(&accessCond_);
    pthread_mutex_unlock(&accessLock_);
}

void SKThread::writerLock()
{
    pthread_mutex_lock(&accessLock_);
    while(readerCount_ || writer_)
    {
	writerWaiting_ = true;
	pthread_cond_wait(&accessCond_, &accessLock_);
    }
    writer_ = true;
    pthread_mutex_unlock(&accessLock_);
}

void SKThread::writerUnlock()
{
    pthread_mutex_lock(&accessLock_);
    writer_ = false;
    writerWaiting_ = false;
    pthread_cond_broadcast(&accessCond_);
    pthread_mutex_unlock(&accessLock_);
}


